<template>
  <div class="a-table">
    <!-- 搜索组件 -->
    <div
      :class="[searchOption.card ? 'task-search-card' : 'task-search']"
      v-if="searchOption.searchForm"
    >
      <el-form
        :model="searchForm"
        class="demo-form-inline"
        :label-width="
          searchOption.searchLabelWidth ? searchOption.searchLabelWidth : 80
        "
        :label-position="
          searchOption.searchLabelPosition
            ? searchOption.searchLabelPosition
            : 'right'
        "
      >
        <el-row :gutter="24">
          <!-- 过滤出search为true的组件 -->
          <template
            v-for="(item, index) in searchOption.columns.filter(
              (it) => it.search
            )"
            :key="item.prop"
          >
            <el-col
              v-if="
                searchOption.searchShowBtn && !expand
                  ? searchOption.maxShowIndex
                    ? index + 1 <= searchOption.maxShowIndex
                    : index + 1 <= 2
                  : searchOption.columns.filter((it) => it.search) ||
                    searchOption.columns.filter((it) => it.search)
              "
              :span="item.search ? searchOption.searchSpan : 0"
              :xs="24"
              :sm="24"
              :md="item.search ? searchOption.searchSpan : 0"
              :lg="item.search ? searchOption.searchSpan : 0"
              :xl="item.search ? searchOption.searchSpan : 0"
            >
              <el-form-item :label="item.label">
                <!-- 输入框 -->
                <el-input
                  v-if="
                    !item.searchSlot &&
                    (!item.searchType || item.searchType == 'input')
                  "
                  v-model="searchForm[item.prop]"
                  :placeholder="
                    item.placeholder ? item.placeholder : `请输入${item.label}`
                  "
                  :clearable="
                    !item.clearable && item.clearable == false ? false : true
                  "
                  :disabled="item.disabled || false"
                  :readonly="item.readonly || false"
                />
                <!-- 下拉框 -->
                <el-select
                  v-if="!item.searchSlot && item.searchType == 'select'"
                  v-model="searchForm[item.prop]"
                  :placeholder="
                    item.placeholder ? item.placeholder : `请选择${item.label}`
                  "
                  :clearable="
                    !item.clearable && item.clearable == false ? false : true
                  "
                  :filterable="item.filterable || false"
                  :multiple="item.multiple || false"
                  :disabled="item.disabled || false"
                  :readonly="item.readonly || false"
                  style="width: 100% !important"
                >
                  <el-option
                    v-for="dic in item.dicData"
                    :key="dic.value"
                    :label="dic.label"
                    :value="dic.value"
                  />
                </el-select>
                <!-- 日期选择器 -->
                <el-date-picker
                  v-if="
                    !item.searchSlot &&
                    (item.searchType == 'date' ||
                      item.searchType == 'datetime' ||
                      item.searchType == 'datetimerange')
                  "
                  v-model="searchForm[item.prop]"
                  :type="item.searchType"
                  :placeholder="
                    item.placeholder ? item.placeholder : `请输入${item.label}`
                  "
                  :clearable="
                    !item.clearable && item.clearable == false ? false : true
                  "
                  :disabled="item.disabled || false"
                  :readonly="item.readonly || false"
                  :format="item.format"
                  :value-format="item.valueFormat"
                  :start-placeholder="item.startPlaceholder"
                  :end-placeholder="item.endPlaceholder"
                  style="width: 100% !important"
                />
                <slot :name="item.prop + 'Search'" v-if="item.searchSlot">
                </slot>
              </el-form-item>
            </el-col>
          </template>
          <span style="margin-left: 12px">
            <slot name="searchMenu"></slot>
            <el-button
              v-if="searchOption.queryBtn"
              type="primary"
              @click="onQuery"
            >
              {{ $t("globalSetting.queryBtn") }}
            </el-button>
            <el-button v-if="searchOption.resetBtn" @click="onReset">
              {{ $t("globalSetting.resetBtn") }}
            </el-button>
            <span v-if="searchOption.searchShowBtn">
              <a
                class="upDown"
                v-if="
                  searchOption.columns.filter((item) => item.search).length >= 3
                "
                @click="expand = !expand"
              >
                {{
                  expand
                    ? $t("globalSetting.retractBtn")
                    : $t("globalSetting.expandBtn")
                }}
                <template v-if="expand">
                  <el-icon style="color: #1890ff"><ArrowUp /></el-icon>
                </template>
                <template v-else>
                  <el-icon style="color: #1890ff"><ArrowDown /></el-icon>
                </template>
              </a>
            </span>
          </span>
        </el-row>
      </el-form>
    </div>
    <!-- 表格组件 -->
    <div :class="[tableOption.card ? 'task-box-card' : 'task-box']">
      <div class="header" v-if="tableOption.header">
        <div class="header-left">
          <el-button
            type="primary"
            v-if="tableOption.addBtn"
            @click="handleAddBtn"
            >{{ $t("globalSetting.addText") }}</el-button
          >
          <slot name="header-left"></slot>
        </div>
        <div class="header-right">
          <slot name="header-right"></slot>
        </div>
      </div>
      <el-table
        :data="getData"
        :border="tableOption.border"
        :stripe="tableOption.stripe"
        :height="tableOption.height"
        :max-height="tableOption.maxheight"
        style="width: 100%"
        ref="multipleTableRef"
        @selection-change="handleSelectionChange"
        :row-class-name="rowclassName"
        @row-click="handleRadioChange"
        :row-key="tableOption.rowKey"
      >
        <template v-for="(row, index) in tableOption.columns" :key="row.prop">
          <el-table-column
            v-if="!row.hide"
            :type="row.type ? row.type : ''"
            :prop="row.prop"
            :label="row.label"
            :align="row.align"
            :width="row.width ? row.width : ''"
            :show-overflow-tooltip="row.showTips"
            :reserve-selection="
              tableOption.selection && tableOption.reserveSelection
                ? true
                : false
            "
            :fixed="
              tableOption.menuFixed && row.prop == 'menu' ? 'right' : null
            "
          >
            <template #default="scope">
              <!-- 切换分页+1页序号 -->
              <template
                v-if="
                  tableOption.indexSort &&
                  tableOption.index &&
                  row.type == 'index'
                "
              >
                {{ (page - 1) * pageSize + scope.$index + 1 }}
              </template>
              <!-- 自定义radio单选 -->
              <slot
                v-if="tableOption.changeRadio && row.prop == 'radio'"
                name="changeRadio"
                :row="data[scope.$index]"
                :index="scope.$index"
              >
              </slot>
              <!-- 自定义table字段 -->
              <slot
                v-if="row.tableSlot"
                :name="row.prop"
                :row="data[scope.$index]"
                :index="scope.$index"
              ></slot>
              <template
                v-if="
                  !row.tableSlot &&
                  row.prop !== 'index' &&
                  row.prop !== 'selection' &&
                  row.prop !== 'radio' &&
                  row.prop !== 'menu'
                "
              >
                {{ getValue(scope, row) }}
              </template>
              <template v-if="tableOption.menu && row.prop == 'menu'">
                <el-button
                  v-if="tableOption.viewBtn"
                  type="text"
                  @click="view(scope.row, scope.$index)"
                  >{{ $t("globalSetting.viewText") }}</el-button
                >
                <el-button
                  v-if="tableOption.editBtn"
                  type="text"
                  @click="update(scope.row, scope.$index)"
                  >{{ $t("globalSetting.editText") }}</el-button
                >
                <el-button
                  v-if="tableOption.delBtn"
                  type="text"
                  @click="del(scope.row, scope.$index)"
                  >{{ $t("globalSetting.delText") }}</el-button
                >
              </template>
              <!-- 自定义操作栏 -->
              <slot
                v-if="tableOption.menu && row.prop == 'menu'"
                name="menu"
                :row="data[scope.$index]"
                :index="scope.$index"
              >
              </slot>
            </template>
          </el-table-column>
        </template>

        <template #empty>
          <div class="noData" v-show="hasRequest">
            <img :src="getAssetsImg('noData')" />

            <p>{{ $t("globalSetting.noData") }}</p>
          </div>
        </template>
      </el-table>
      <div :class="{ hidden: hidden }" class="pagination-container">
        <el-config-provider :locale="locale">
          <el-pagination
            v-show="total > 0"
            :background="background"
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :layout="layout"
            :page-sizes="pageSizes"
            :pager-count="pagerCount"
            :total="total"
            :small="small"
            v-bind="$attrs"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-config-provider>
      </div>
    </div>

    <a-dialog
      :dialogOption="option"
      v-model="dialogVisible"
      @handleClose="handleClose"
      @confirmDialog="rowSave"
      @editDialog="rowUpdate"
      :type="dialogType"
      :modalWidth="option.modalWidth"
    >
      <a-form-dialog
        v-if="dialogVisible && (dialogType == 'add' || dialogType == 'edit')"
        ref="ruleFormValidate"
        :formOption="formOption"
        v-model="formDialog"
        :type="dialogType"
      >
        <!-- 配置label自定义插槽 -->
        <template #label="{ formItem }">
          <slot :name="formItem.prop + 'Label'"></slot>
        </template>
        <!-- 配置form自定义插槽 -->
        <template #form="{ formItem }">
          <slot
            :name="formItem.prop + 'Form'"
            :disabled="formItem.disabled"
            :readonly="formItem.readonly"
          ></slot>
        </template>
      </a-form-dialog>
      <!-- 配置只读表单 -->
      <a-form-desc
        v-if="dialogVisible && dialogType == 'view'"
        :formType="'table'"
        v-model="formDialog"
        :formOption="formDescOption"
      >
        <!-- 配置只读表单自定义插槽 -->
        <template #form="{ formItem }">
          <slot :name="formItem.prop + 'Form'"></slot>
        </template>
      </a-form-desc>
      <!-- 配置弹窗按钮自定义插槽 -->
      <template #footer="{ type }">
        <slot name="footerDialog" :type="type"></slot>
      </template>
    </a-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ElConfigProvider } from "element-plus";
import elzhCN from "element-plus/es/locale/lang/zh-cn";
import { handleElementLang } from "@/lang";
import aDialog from "../aDialog"; // 引用弹框
import aFormDialog from "../aFormDialog"; // 引用form组件
import aFormDesc from "../aFormDesc"; // 引入只读form组件
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const locale = ref(elzhCN);
const expand = ref(false);
const dialogType = ref("add");
const ruleFormValidate = ref();
const emit = defineEmits();
const props = defineProps({
  modelValue: {
    type: Object,
    default: {},
  },
  form: {
    type: Object,
    default: {},
  },
  data: {
    type: Array,
    default: [],
  },
  option: {
    type: Object,
    default: {},
  },
  pagerCount: {
    type: Number,
    default: 8,
  },
  total: {
    required: true,
    type: Number,
  },
  page: {
    type: Number,
    default: 1,
  },
  limit: {
    type: Number,
    default: 20,
  },
  pageSizes: {
    type: Array,
    default() {
      return [10, 20, 30, 50];
    },
  },
  layout: {
    type: String,
    default: "total, sizes, prev, pager, next, jumper",
  },
  background: {
    type: Boolean,
    default: true,
  },
  small: {
    type: Boolean,
    default: false,
  },
  hidden: {
    type: Boolean,
    default: false,
  },
  hasRequest: {
    type: Boolean,
    default: false,
  },
});

const {
  modelValue,
  data,
  option,
  total,
  page,
  limit,
  pageSizes,
  layout,
  background,
  small,
  hidden,
  hasRequest,
  pagerCount,
  form,
} = toRefs(props);

const getData = computed(() => {
  // 深拷贝data数据，避免直接修改原数据
  return JSON.parse(JSON.stringify(data.value));
});

const multipleTableRef = ref();
const cloneForm = ref();
const formDialog = computed({
  get() {
    return form.value;
  },
  set(value) {
    emit("update:form", value);
  },
});

// 搜索组件
const searchForm = computed({
  get() {
    return modelValue.value;
  },
  set(value) {
    emit("update:modelValue", value);
  },
});

// 搜索组件配置
const searchOption = computed(() => {
  // 深拷贝数组配置，每个组件维护自己的数组配置
  let optionData = JSON.parse(JSON.stringify(option.value.columns));

  const searchOrderFlag = optionData.some((item) => item.searchOrder);

  if (searchOrderFlag) {
    optionData.sort((a, b) => {
      const searchOrderA = a.searchOrder;
      const searchOrderB = b.searchOrder;

      // 如果a有searchOrder而b没有，则a排在前面
      if (searchOrderA && !searchOrderB) return -1;
      // 如果b有searchOrder而a没有，则b排在前面
      if (!searchOrderA && searchOrderB) return 1;
      // 如果两者都有或两者都没有，则按searchOrder排序
      if (searchOrderA && searchOrderB) return searchOrderA - searchOrderB;
      // 如果两者都没有searchOrder，则默认顺序（这里可以自定义，比如返回0保持原顺序）
      return 0;
    });
  }
  return { ...option.value, columns: optionData };
});

// 表单组件配置
const formOption = computed(() => {
  // 深拷贝数组配置，每个组件维护自己的数组配置
  let optionData = JSON.parse(JSON.stringify(option.value.columns));

  const formOrderFlag = optionData.some((item) => item.formOrder);

  if (formOrderFlag) {
    optionData.sort((a, b) => {
      const formOrderA = a.formOrder;
      const formOrderB = b.formOrder;

      // 如果a有formOrder而b没有，则a排在前面
      if (formOrderA && !formOrderB) return -1;
      // 如果b有formOrder而a没有，则b排在前面
      if (!formOrderA && formOrderB) return 1;
      // 如果两者都有或两者都没有，则按formOrder排序
      if (formOrderA && formOrderB) return formOrderA - formOrderB;
      // 如果两者都没有formOrder，则默认顺序（这里可以自定义，比如返回0保持原顺序）
      return 0;
    });
  }
  return { ...option.value, columns: optionData };
});

// 只读表单组件配置
const formDescOption = computed(() => {
  // 深拷贝数组配置，每个组件维护自己的数组配置
  let optionValue = JSON.parse(JSON.stringify(option.value));

  optionValue.card = false;
  optionValue.closeBtn = false;
  optionValue.border = true;
  optionValue.space = true;

  let optionData = JSON.parse(JSON.stringify(option.value.columns));

  const formOrderFlag = optionData.some((item) => item.formOrder);

  if (formOrderFlag) {
    optionData.sort((a, b) => {
      const formOrderA = a.formOrder;
      const formOrderB = b.formOrder;

      // 如果a有formOrder而b没有，则a排在前面
      if (formOrderA && !formOrderB) return -1;
      // 如果b有formOrder而a没有，则b排在前面
      if (!formOrderA && formOrderB) return 1;
      // 如果两者都有或两者都没有，则按formOrder排序
      if (formOrderA && formOrderB) return formOrderA - formOrderB;
      // 如果两者都没有formOrder，则默认顺序（这里可以自定义，比如返回0保持原顺序）
      return 0;
    });
  }
  optionData = optionData.filter((item) => item.viewDisplay !== false);
  let propList = [];
  optionData.forEach((item) => {
    if (item.type === "select" && item.dicData && item.dicData.length) {
      if (
        typeof formDialog.value[item.prop] === "string" ||
        typeof formDialog.value[item.prop] === "number"
      ) {
        const objProp = item.dicData.find(
          (it) => it.value == formDialog.value[item.prop]
        );
        if (objProp !== undefined) {
          formDialog.value[item.prop] = objProp.label;
        }
      } else {
        item.dicData.forEach((it) => {
          formDialog.value[item.prop].forEach((el) => {
            if (it.value == el) {
              propList.push(it.label);
            }
          });
        });
        formDialog.value[item.prop] =
          propList?.join("|") || formDialog.value[item.prop]?.join("|");
      }
    }
    item.formSlot = false;
  });
  return {
    ...optionValue,
    columns: optionData,
  };
});

// 表格组件配置
const tableOption = computed(() => {
  // 深拷贝数组配置，每个组件维护自己的数组配置
  let optionData = JSON.parse(JSON.stringify(option.value.columns));

  const tableOrderFlag = optionData.some((item) => item.tableOrder);
  if (tableOrderFlag) {
    optionData.sort((a, b) => {
      const tableOrderA = a.tableOrder;
      const tableOrderB = b.tableOrder;

      // 如果a有tableOrder而b没有，则a排在前面
      if (tableOrderA && !tableOrderB) return -1;
      // 如果b有tableOrder而a没有，则b排在前面
      if (!tableOrderA && tableOrderB) return 1;
      // 如果两者都有或两者都没有，则按tableOrder排序
      if (tableOrderA && tableOrderB) return tableOrderA - tableOrderB;
      // 如果两者都没有tableOrder，则默认顺序（这里可以自定义，比如返回0保持原顺序）
      return 0;
    });
  }

  if (option.value.selection) {
    optionData = [
      {
        label: "",
        prop: "selection",
        type: "selection",
        width: option.value.selectionWidth || 50,
        align: option.value.selectionAlign,
      },
      ...optionData,
    ];
  }
  if (option.value.changeRadio) {
    optionData = [
      {
        label: option.value.radioLabel || "",
        prop: "radio",
        width: option.value.radioWidth || 50,
        align: option.value.radioAlign, // left|center|right
      },
      ...optionData,
    ];
  }
  if (option.value.index) {
    optionData = [
      {
        label: option.value.indexLabel,
        prop: "index",
        type: "index",
        width: option.value.indexWidth || 70,
        align: option.value.indexAlign, // left|center|right
      },
      ...optionData,
    ];
  }
  if (option.value.menu) {
    optionData = [
      ...optionData,
      {
        label: option.value.menuLabel,
        prop: "menu",
        width: option.value.menuWidth || 150,
        align: option.value.menuAlign, // left|center|right
      },
    ];
  }

  // let data = { ...option.value, columns: optionData }
  // console.log('data====', data)
  return { ...option.value, columns: optionData };
});

const getValue = computed(() => {
  return (scope, row) => {
    let propList = [];
    if (
      row.searchType == "select" ||
      (row.type == "select" && row.dicData && row.dicData.length)
    ) {
      if (
        typeof scope.row[row.prop] === "string" ||
        typeof scope.row[row.prop] === "number"
      ) {
        let obj = row.dicData.find((it) => it.value == scope.row[row.prop]);
        if (obj !== undefined) {
          return (scope.row[row.prop] = obj.label);
        } else {
          return scope.row[row.prop];
        }
      } else {
        row.dicData.forEach((it) => {
          scope.row[row.prop].forEach((el) => {
            if (it.value == el) {
              propList.push(it.label);
            }
          });
        });
        return (scope.row[row.prop] =
          propList?.join("|") || scope.row[row.prop]?.join("|"));
      }
    } else {
      return scope.row[row.prop];
    }
  };
});

// 多选
function handleSelectionChange(value) {
  let indexlist = value.map((item) => {
    return item.index;
  });
  let newData = [];
  indexlist.forEach((it) => {
    data.value.forEach((item, index) => {
      if (index == it) {
        newData.push(item);
      }
    });
  });
  emit("handleSelectionChange", newData);
}

function rowclassName({ row, rowIndex }) {
  row.index = rowIndex;
}

// 行点击
function handleRadioChange(row) {
  //   console.log('行下标：', row.index);
  if (tableOption.value.rowClick) {
    // 获取当前行点击的下标
    row = data.value[row.index];
    const index = data.value.indexOf(row);
    // 如果开启了changeRadio，则将当前行数据传递出去
    emit("handleRadioChange", row, index);
  }
}

const currentPage = computed({
  get() {
    return props.page;
  },
  set(val) {
    emit("update:page", val);
  },
});

// 计算当前page
const pageSize = computed({
  get() {
    return props.limit;
  },
  set(val) {
    emit("update:limit", val);
  },
});

// 切换size
const handleSizeChange = (val) => {
  emit("pagination", { page: currentPage, limt: val });
};

// 切换page
const handleCurrentChange = (val) => {
  emit("pagination", { page: val, limt: pageSize });
};

// 初始化列表
const onLoad = () => {
  emit("on-load");
};

// 获取搜索表单值的方法
function onQuery() {
  emit("onQuery", searchForm.value);
}

// 重置搜索表单值的方法
function onReset() {
  searchForm.value = {};
  emit("onReset", searchForm.value);
}

const dialogVisible = ref(false);

// 开启新增弹窗
function handleAddBtn() {
  cloneForm.value = JSON.parse(JSON.stringify(form.value));
  // formDialog.value = Object.assign(formDialog.value, form.value);
  dialogType.value = "add";
  dialogVisible.value = true;
  emit("handleAddBtn");
}

// 开启查看弹窗将原始数据拷贝一份
function view(row, index) {
  row = index >= 0 ? data.value[index] : row;
  dialogType.value = "view";
  cloneForm.value = JSON.parse(JSON.stringify(form.value));
  formDialog.value = JSON.parse(JSON.stringify(row));
  dialogVisible.value = true;
  emit("row-view", row, index);
}
// 开启编辑弹窗将原始数据拷贝一份
function update(row, index) {
  row = index >= 0 ? data.value[index] : row;
  dialogType.value = "edit";
  cloneForm.value = JSON.parse(JSON.stringify(form.value));
  formDialog.value = JSON.parse(JSON.stringify(row));
  dialogVisible.value = true;
  emit("update", row, index);
}

// 关闭弹框
function handleClose(done) {
  dialogVisible.value = done;
  formDialog.value = cloneForm.value;
}

// 提交表单
async function rowSave(done) {
  const res = await ruleFormValidate.value.onSubmit();
  if (res) {
    dialogVisible.value = done;
    emit("row-save", formDialog.value, handleClose);
  }
}

// 编辑表单
async function rowUpdate(done) {
  const res = await ruleFormValidate.value.onSubmit();
  if (res) {
    dialogVisible.value = done;
    emit("row-update", formDialog.value, handleClose);
  }
}

// 删除方法
function del(row, index) {
  emit("row-del", row, index);
}

// 初始化函数
onBeforeMount(() => {
  onLoad();
  locale.value = handleElementLang();
});

defineExpose({
  handleSelectionChange,
  handleRadioChange,
  multipleTableRef,
  onQuery,
  onReset,
  handleAddBtn,
  rowSave,
  rowUpdate,
  update,
  del,
  view,
  handleClose,
});
</script>

<style lang="scss" scoped>
.a-table {
  .task-search {
    background: #fff;
    // margin-bottom: 20px;
    padding: 24px 24px 5px 32px;
  }
  .task-search-card {
    background: #fff;
    margin-bottom: 20px;
    padding: 24px 24px 24px 32px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    // box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3);
  }
  .task-box {
    background: #fff;
    padding: 16px 30px;
  }
  .task-box-card {
    background: #fff;
    padding: 16px 30px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    // box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3);
  }
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
  }
  .pagination-container {
    display: flex;
    flex-direction: row;
    justify-content: center;
    padding: 20px 0;
  }
  .upDown {
    font-size: 12px;
    color: #1890ff !important;
    margin-left: 10px;
    cursor: pointer;
  }
  .noData {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 100px 0;

    img {
      width: 215px;
      height: 150px;
      margin-bottom: 10px;
    }
  }
}
</style>
